package controllers

import (
	"log"
	"net/http"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/vulnark/vulnark/models"
	"github.com/vulnark/vulnark/utils"
)

// VulnerabilityAssignmentController 漏洞分发控制器
type VulnerabilityAssignmentController struct{}

// AssignVulnerability 分派漏洞
func (va *VulnerabilityAssignmentController) AssignVulnerability(c *gin.Context) {
	// 记录请求信息
	log.Printf("收到漏洞分派请求 - 路径参数: %v, 请求方法: %s, 完整路径: %s", c.Params, c.Request.Method, c.Request.URL.Path)

	// 获取当前用户ID
	userID, exists := c.Get("userID")
	if !exists {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "无法获取当前用户ID",
		})
		return
	}

	// 从URL路径中获取漏洞ID
	vulnIDStr := c.Param("id")
	vulnID, err := strconv.ParseUint(vulnIDStr, 10, 32)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "无效的漏洞ID",
			"error":   err.Error(),
		})
		return
	}

	// 解析请求数据
	var assignment models.VulnerabilityAssignment
	if err := c.ShouldBindJSON(&assignment); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "无效的请求数据",
			"error":   err.Error(),
		})
		return
	}

	// 使用URL中的漏洞ID覆盖请求体中的ID
	assignment.VulnerabilityID = uint(vulnID)

	// 验证漏洞是否存在
	var vulnerability models.Vulnerability
	if err := utils.DB.First(&vulnerability, assignment.VulnerabilityID).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{
			"code":    404,
			"message": "漏洞不存在",
		})
		return
	}

	// 验证指派目标用户是否存在
	var user models.User
	if err := utils.DB.First(&user, assignment.AssignedToID).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{
			"code":    404,
			"message": "目标用户不存在",
		})
		return
	}

	// 设置默认值
	assignment.AssignedByID = userID.(uint)
	assignment.Status = models.AssignmentStatusPending
	assignment.CreatedAt = time.Now()
	assignment.UpdatedAt = time.Now()

	// 保存分配信息
	if err := utils.DB.Create(&assignment).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "保存漏洞分配失败",
			"error":   err.Error(),
		})
		return
	}

	// 创建分配历史记录
	history := models.VulnerabilityAssignmentHistory{
		AssignmentID: assignment.ID,
		Status:       models.AssignmentStatusPending,
		Comment:      "漏洞分配创建",
		ChangedByID:  userID.(uint),
		CreatedAt:    time.Now(),
	}

	if err := utils.DB.Create(&history).Error; err != nil {
		// 仅记录日志，不影响主流程
		log.Printf("创建漏洞分配历史记录失败: %v", err)
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "漏洞分配成功",
		"data":    assignment,
	})
}

// UpdateAssignmentStatus 更新漏洞分发状态
func (va *VulnerabilityAssignmentController) UpdateAssignmentStatus(c *gin.Context) {
	// 获取当前用户ID
	userID, exists := c.Get("userID")
	if !exists {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "无法获取当前用户ID",
		})
		return
	}

	// 解析路径参数
	assignmentID, err := strconv.ParseUint(c.Param("id"), 10, 32)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "无效的ID",
		})
		return
	}

	// 解析请求数据
	type UpdateStatusRequest struct {
		Status   string `json:"status" binding:"required"`
		Response string `json:"response"`
		Comment  string `json:"comment"`
	}

	var req UpdateStatusRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "无效的请求数据",
			"error":   err.Error(),
		})
		return
	}

	// 验证状态值
	validStatuses := map[string]bool{
		models.AssignmentStatusPending:      true,
		models.AssignmentStatusAccepted:     true,
		models.AssignmentStatusRejected:     true,
		models.AssignmentStatusFixed:        true,
		models.AssignmentStatusPendingRetest: true,
		models.AssignmentStatusClosed:       true,
	}

	if !validStatuses[req.Status] {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "无效的状态值",
		})
		return
	}

	// 查询分派记录
	var assignment models.VulnerabilityAssignment
	if err := utils.DB.Preload("AssignedTo").Preload("AssignedBy").Preload("Vulnerability").First(&assignment, assignmentID).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{
			"code":    404,
			"message": "分派记录不存在",
		})
		return
	}

	// 保存旧状态用于后续处理
	oldStatus := assignment.Status

	// 更新状态
	assignment.Status = req.Status
	assignment.Response = req.Response
	assignment.UpdatedAt = time.Now()

	if err := utils.DB.Save(&assignment).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "更新分派状态失败",
			"error":   err.Error(),
		})
		return
	}
	
	// 如果状态变更为待复测，发送通知给管理员
	if req.Status == models.AssignmentStatusPendingRetest && oldStatus != models.AssignmentStatusPendingRetest {
		go func() {
			// 获取管理员用户列表
			var admins []models.User
			if err := utils.DB.Where("role = ?", "admin").Find(&admins).Error; err != nil {
				log.Printf("获取管理员列表失败: %v", err)
				return
			}

			// 发送通知
			notificationManager, err := utils.NewNotificationManager()
			if err != nil {
				log.Printf("获取通知管理器失败: %v", err)
				return
			}

			// 使用漏洞状态变更事件发送通知
			notificationManager.SendVulnerabilityNotification(utils.EventVulnStatusChange, &assignment.Vulnerability, string(oldStatus))

			// 记录日志
			log.Printf("已发送漏洞复测申请通知，漏洞ID: %d, 标题: %s", assignment.VulnerabilityID, assignment.Vulnerability.Title)
		}()
	}

	// 创建状态更新历史
	history := models.VulnerabilityAssignmentHistory{
		AssignmentID: assignment.ID,
		Status:       req.Status,
		Comment:      req.Comment,
		ChangedByID:  userID.(uint),
		CreatedAt:    time.Now(),
	}

	if err := utils.DB.Create(&history).Error; err != nil {
		// 仅记录日志，不影响主流程
		log.Printf("创建漏洞分配历史记录失败: %v", err)
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "更新分派状态成功",
		"data":    assignment,
	})
}

// GetAssignmentsByVulnerability 获取漏洞的所有分派历史
func (va *VulnerabilityAssignmentController) GetAssignmentsByVulnerability(c *gin.Context) {
	// 获取漏洞ID
	vulnID, err := strconv.ParseUint(c.Param("id"), 10, 32)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "无效的漏洞ID",
		})
		return
	}

	// 查询分派记录
	var assignments []models.VulnerabilityAssignment
	query := utils.DB.
		Preload("AssignedTo").
		Preload("AssignedBy").
		Order("created_at DESC").
		Where("vulnerability_id = ?", vulnID).
		Find(&assignments)

	if query.Error != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "查询分派记录失败",
			"error":   query.Error.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "获取分派记录成功",
		"data":    assignments,
		"total":   len(assignments),
	})
}

// GetMyAssignments 获取当前用户的分派任务
func (va *VulnerabilityAssignmentController) GetMyAssignments(c *gin.Context) {
	// 获取当前用户ID
	userID, exists := c.Get("userID")
	if !exists {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "无法获取当前用户ID",
		})
		return
	}

	// 解析查询参数
	status := c.DefaultQuery("status", "")
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("pageSize", "10"))

	// 计算分页偏移
	offset := (page - 1) * pageSize

	// 构建查询
	query := utils.DB.Model(&models.VulnerabilityAssignment{}).
		Preload("Vulnerability").
		Preload("AssignedBy").
		Where("assigned_to_id = ?", userID)

	// 按状态过滤
	if status != "" {
		query = query.Where("status = ?", status)
	}

	// 计算总数
	var total int64
	if err := query.Count(&total).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "查询分派记录总数失败",
			"error":   err.Error(),
		})
		return
	}

	// 获取分页数据
	var assignments []models.VulnerabilityAssignment
	if err := query.Offset(offset).Limit(pageSize).Order("created_at DESC").Find(&assignments).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "查询分派记录失败",
			"error":   err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":     200,
		"message":  "获取我的任务成功",
		"data":     assignments,
		"total":    total,
		"page":     page,
		"pageSize": pageSize,
	})
}

// GetAssignmentDetails 获取分派任务详情
func (va *VulnerabilityAssignmentController) GetAssignmentDetails(c *gin.Context) {
	// 解析路径参数
	assignmentID, err := strconv.ParseUint(c.Param("id"), 10, 32)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "无效的ID",
		})
		return
	}

	// 查询分派记录
	var assignment models.VulnerabilityAssignment
	if err := utils.DB.
		Preload("Vulnerability").
		Preload("AssignedTo").
		Preload("AssignedBy").
		First(&assignment, assignmentID).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{
			"code":    404,
			"message": "分派记录不存在",
		})
		return
	}

	// 查询历史记录
	var history []models.VulnerabilityAssignmentHistory
	if err := utils.DB.
		Preload("ChangedBy").
		Where("assignment_id = ?", assignmentID).
		Order("created_at DESC").
		Find(&history).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "查询历史记录失败",
			"error":   err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "获取分派详情成功",
		"data": gin.H{
			"assignment": assignment,
			"history":    history,
		},
	})
}

// ListAssignments 管理员列出所有分派任务
func (va *VulnerabilityAssignmentController) ListAssignments(c *gin.Context) {
	// 解析查询参数
	status := c.DefaultQuery("status", "")
	assignedTo := c.DefaultQuery("assignedTo", "")
	vulnID := c.DefaultQuery("vulnId", "")
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("pageSize", "10"))

	// 计算分页偏移
	offset := (page - 1) * pageSize

	// 构建查询
	query := utils.DB.Model(&models.VulnerabilityAssignment{}).
		Preload("Vulnerability").
		Preload("AssignedTo").
		Preload("AssignedBy")

	// 按条件过滤
	if status != "" {
		query = query.Where("status = ?", status)
	}
	if assignedTo != "" {
		query = query.Where("assigned_to_id = ?", assignedTo)
	}
	if vulnID != "" {
		query = query.Where("vulnerability_id = ?", vulnID)
	}

	// 计算总数
	var total int64
	if err := query.Count(&total).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "查询分派记录总数失败",
			"error":   err.Error(),
		})
		return
	}

	// 获取分页数据
	var assignments []models.VulnerabilityAssignment
	if err := query.Offset(offset).Limit(pageSize).Order("created_at DESC").Find(&assignments).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "查询分派记录失败",
			"error":   err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":     200,
		"message":  "获取分派任务列表成功",
		"data":     assignments,
		"total":    total,
		"page":     page,
		"pageSize": pageSize,
	})
}

// DeleteAssignment 删除分派任务
func (va *VulnerabilityAssignmentController) DeleteAssignment(c *gin.Context) {
	// 解析路径参数
	assignmentID, err := strconv.ParseUint(c.Param("id"), 10, 32)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "无效的ID",
		})
		return
	}

	// 查询分派记录
	var assignment models.VulnerabilityAssignment
	if err := utils.DB.First(&assignment, assignmentID).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{
			"code":    404,
			"message": "分派记录不存在",
		})
		return
	}

	// 删除历史记录
	if err := utils.DB.Where("assignment_id = ?", assignmentID).Delete(&models.VulnerabilityAssignmentHistory{}).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "删除历史记录失败",
			"error":   err.Error(),
		})
		return
	}

	// 删除分派记录
	if err := utils.DB.Delete(&assignment).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "删除分派记录失败",
			"error":   err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "删除分派记录成功",
	})
}
